<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Webpack 火焰图分析器</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            margin: 0;
            padding: 20px;
            background: #f5f5f5;
        }
        .container {
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            overflow: hidden;
        }
        .header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 20px;
            text-align: center;
        }
        .stats-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
            gap: 20px;
            padding: 20px;
        }
        .stat-card {
            background: #f8f9fa;
            border-radius: 8px;
            padding: 20px;
            text-align: center;
            border-left: 4px solid #667eea;
        }
        .stat-value {
            font-size: 2rem;
            font-weight: bold;
            color: #667eea;
            margin-bottom: 10px;
        }
        .stat-label {
            color: #666;
            font-size: 0.9rem;
        }
        .flamegraph {
            margin: 20px;
            padding: 20px;
            background: #f8f9fa;
            border-radius: 8px;
        }
        .module-item {
            background: white;
            margin: 10px 0;
            padding: 15px;
            border-radius: 6px;
            border-left: 4px solid #4ecdc4;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        .module-name {
            font-weight: bold;
            color: #333;
            margin-bottom: 5px;
        }
        .module-stats {
            display: flex;
            gap: 20px;
            font-size: 0.9rem;
            color: #666;
        }
        .performance-bar {
            background: #e9ecef;
            height: 8px;
            border-radius: 4px;
            margin: 10px 0;
            overflow: hidden;
        }
        .performance-fill {
            height: 100%;
            background: linear-gradient(90deg, #4ecdc4, #44a08d);
            transition: width 0.3s ease;
        }
        .loading {
            text-align: center;
            padding: 40px;
            color: #666;
        }
        .error {
            background: #f8d7da;
            color: #721c24;
            padding: 15px;
            border-radius: 6px;
            margin: 20px;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🔥 Webpack 火焰图分析器</h1>
            <p>构建性能分析和优化建议</p>
        </div>
        
        <div id="content">
            <div class="loading">正在加载分析数据...</div>
        </div>
    </div>

    <script>
        class FlamegraphAnalyzer {
            constructor() {
                this.statsData = null;
                this.init();
            }

            async init() {
                try {
                    await this.loadStatsData();
                    this.renderAnalysis();
                } catch (error) {
                    this.showError('无法加载统计数据: ' + error.message);
                }
            }

            async loadStatsData() {
                try {
                    const response = await fetch('./dist/bundle-stats.json');
                    if (!response.ok) {
                        throw new Error('HTTP ' + response.status);
                    }
                    this.statsData = await response.json();
                } catch (error) {
                    throw new Error('请确保已运行 npm run webpack:profile 生成统计数据');
                }
            }

            renderAnalysis() {
                const content = document.getElementById('content');
                content.innerHTML = `
                    <div class="stats-grid">
                        ${this.renderOverviewStats()}
                    </div>
                    <div class="flamegraph">
                        <h2>📊 模块构建性能分析</h2>
                        ${this.renderModuleAnalysis()}
                    </div>
                    <div class="flamegraph">
                        <h2>⚡ 性能优化建议</h2>
                        ${this.renderOptimizationTips()}
                    </div>
                `;
            }

            renderOverviewStats() {
                const { time, assets, chunks } = this.statsData;
                const totalSize = assets.reduce((sum, asset) => sum + asset.size, 0);
                const avgModuleTime = this.calculateAverageModuleTime();

                return `
                    <div class="stat-card">
                        <div class="stat-value">${(time / 1000).toFixed(2)}s</div>
                        <div class="stat-label">总构建时间</div>
                    </div>
                    <div class="stat-card">
                        <div class="stat-value">${(totalSize / 1024).toFixed(1)}KB</div>
                        <div class="stat-label">总包大小</div>
                    </div>
                    <div class="stat-card">
                        <div class="stat-value">${chunks.length}</div>
                        <div class="stat-label">代码块数量</div>
                    </div>
                    <div class="stat-card">
                        <div class="stat-value">${avgModuleTime.toFixed(0)}ms</div>
                        <div class="stat-label">平均模块构建时间</div>
                    </div>
                `;
            }

            renderModuleAnalysis() {
                const modules = this.getModulesWithProfile();
                const maxTime = Math.max(...modules.map(m => m.profile.total));

                return modules.map(module => {
                    const percentage = (module.profile.total / maxTime) * 100;
                    const buildTime = module.profile.building;
                    const resolveTime = module.profile.resolving;

                    return `
                        <div class="module-item">
                            <div class="module-name">${this.getModuleDisplayName(module.name)}</div>
                            <div class="performance-bar">
                                <div class="performance-fill" style="width: ${percentage}%"></div>
                            </div>
                            <div class="module-stats">
                                <span>总时间: ${module.profile.total}ms</span>
                                <span>构建: ${buildTime}ms</span>
                                <span>解析: ${resolveTime}ms</span>
                                <span>大小: ${(module.size / 1024).toFixed(1)}KB</span>
                            </div>
                        </div>
                    `;
                }).join('');
            }

            renderOptimizationTips() {
                const tips = this.generateOptimizationTips();
                return `
                    <div style="padding: 20px;">
                        ${tips.map(tip => `
                            <div class="module-item" style="margin-bottom: 15px;">
                                <div class="module-name">💡 ${tip.title}</div>
                                <div style="color: #666; margin-top: 5px;">${tip.description}</div>
                            </div>
                        `).join('')}
                    </div>
                `;
            }

            getModulesWithProfile() {
                const modules = [];
                this.statsData.chunks.forEach(chunk => {
                    chunk.modules.forEach(module => {
                        if (module.profile) {
                            modules.push(module);
                        }
                    });
                });
                return modules.sort((a, b) => b.profile.total - a.profile.total);
            }

            getModuleDisplayName(name) {
                return name.replace(/^\.\/node_modules\//, '📦 ')
                          .replace(/^\.\/src\//, '📁 ')
                          .replace(/\.(ts|js|css)$/, '')
                          .replace(/\./g, '/');
            }

            calculateAverageModuleTime() {
                const modules = this.getModulesWithProfile();
                if (modules.length === 0) return 0;
                const totalTime = modules.reduce((sum, m) => sum + m.profile.total, 0);
                return totalTime / modules.length;
            }

            generateOptimizationTips() {
                const tips = [];
                const { time } = this.statsData;
                const modules = this.getModulesWithProfile();

                // 分析构建时间
                if (time > 10000) {
                    tips.push({
                        title: '构建时间过长',
                        description: '总构建时间超过10秒，建议启用缓存和并行处理'
                    });
                }

                // 分析模块构建时间
                const slowModules = modules.filter(m => m.profile.total > 1000);
                if (slowModules.length > 0) {
                    tips.push({
                        title: '慢模块检测',
                        description: `发现 ${slowModules.length} 个构建时间超过1秒的模块，建议优化`
                    });
                }

                // 分析解析时间
                const highResolveTime = modules.filter(m => m.profile.resolving > 500);
                if (highResolveTime.length > 0) {
                    tips.push({
                        title: '模块解析优化',
                        description: '部分模块解析时间较长，建议检查依赖关系'
                    });
                }

                // 通用优化建议
                tips.push({
                    title: '缓存优化',
                    description: '启用 webpack 缓存和 loader 缓存以提高重复构建速度'
                });

                tips.push({
                    title: '并行处理',
                    description: '使用 thread-loader 或 parallel-webpack 进行并行构建'
                });

                return tips;
            }

            showError(message) {
                const content = document.getElementById('content');
                content.innerHTML = `
                    <div class="error">
                        <strong>错误:</strong> ${message}
                    </div>
                `;
            }
        }

        // 初始化分析器
        new FlamegraphAnalyzer();
    </script>
</body>
</html> 